#!/bin/bash

# SSL证书问题修复脚本
# 解决Let's Encrypt验证失败的问题

set -e

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 检查域名解析
check_dns() {
    local domain=$1
    log_info "检查域名解析: $domain"
    
    # 使用多个DNS服务器检查
    for dns in "8.8.8.8" "1.1.1.1" "114.114.114.114"; do
        echo "使用DNS $dns 查询 $domain:"
        dig @$dns +short $domain || echo "查询失败"
    done
    
    echo "使用nslookup查询:"
    nslookup $domain || echo "nslookup失败"
}

# 检查端口连通性
check_port() {
    local domain=$1
    local port=$2
    log_info "检查端口连通性: $domain:$port"
    
    if command -v nc &> /dev/null; then
        if nc -z -w5 $domain $port; then
            log_info "端口 $port 可达"
        else
            log_warn "端口 $port 不可达"
        fi
    else
        log_warn "nc命令不可用，跳过端口检查"
    fi
}

# 检查防火墙状态
check_firewall() {
    log_info "检查防火墙状态..."
    
    # 检查ufw
    if command -v ufw &> /dev/null; then
        echo "UFW状态:"
        ufw status
    fi
    
    # 检查iptables
    if command -v iptables &> /dev/null; then
        echo "iptables规则 (INPUT链):"
        iptables -L INPUT -n --line-numbers | head -20
    fi
    
    # 检查云服务器安全组（腾讯云）
    log_warn "请确保云服务器安全组已开放80和443端口"
}

# 测试HTTP连接
test_http_connection() {
    local domain=$1
    log_info "测试HTTP连接: $domain"
    
    # 测试从外部访问
    if curl -I --connect-timeout 10 "http://$domain" 2>/dev/null; then
        log_info "HTTP连接正常"
    else
        log_warn "HTTP连接失败"
    fi
    
    # 测试本地连接
    if curl -I --connect-timeout 5 "http://localhost" 2>/dev/null; then
        log_info "本地HTTP连接正常"
    else
        log_warn "本地HTTP连接失败"
    fi
}

# 方案1：只为主域名获取证书
get_cert_main_domain_only() {
    local domain=$1
    local email=$2
    
    log_info "方案1: 只为主域名获取证书"
    log_info "域名: $domain"
    
    # 停止nginx
    docker-compose -f docker-compose.prod.yml stop nginx || true
    
    # 只为主域名获取证书
    certbot certonly \
        --standalone \
        --non-interactive \
        --agree-tos \
        --email "$email" \
        -d "$domain" \
        --cert-path /etc/letsencrypt/live/$domain/cert.pem \
        --key-path /etc/letsencrypt/live/$domain/privkey.pem \
        --fullchain-path /etc/letsencrypt/live/$domain/fullchain.pem \
        --chain-path /etc/letsencrypt/live/$domain/chain.pem
    
    if [ $? -eq 0 ]; then
        log_info "主域名证书获取成功"
        return 0
    else
        log_error "主域名证书获取失败"
        return 1
    fi
}

# 方案2：使用webroot模式
get_cert_webroot() {
    local domain=$1
    local email=$2
    
    log_info "方案2: 使用webroot模式获取证书"
    
    # 创建webroot目录
    mkdir -p /var/www/certbot
    
    # 启动临时nginx配置
    cat > /tmp/nginx-temp.conf << EOF
server {
    listen 80;
    server_name $domain www.$domain;
    
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    
    location / {
        return 200 'OK';
        add_header Content-Type text/plain;
    }
}
EOF
    
    # 启动临时nginx容器
    docker run -d --name temp-nginx \
        -p 80:80 \
        -v /tmp/nginx-temp.conf:/etc/nginx/conf.d/default.conf \
        -v /var/www/certbot:/var/www/certbot \
        nginx:alpine
    
    sleep 5
    
    # 使用webroot模式获取证书
    certbot certonly \
        --webroot \
        --webroot-path=/var/www/certbot \
        --non-interactive \
        --agree-tos \
        --email "$email" \
        -d "$domain" \
        -d "www.$domain"
    
    local result=$?
    
    # 清理临时容器
    docker stop temp-nginx || true
    docker rm temp-nginx || true
    
    if [ $result -eq 0 ]; then
        log_info "webroot模式证书获取成功"
        return 0
    else
        log_error "webroot模式证书获取失败"
        return 1
    fi
}

# 复制证书文件
copy_certificates() {
    local domain=$1
    
    log_info "复制证书文件..."
    
    if [ -f "/etc/letsencrypt/live/$domain/fullchain.pem" ]; then
        cp /etc/letsencrypt/live/$domain/fullchain.pem ./ssl-certs/
        cp /etc/letsencrypt/live/$domain/privkey.pem ./ssl-certs/
        chmod 644 ./ssl-certs/fullchain.pem
        chmod 600 ./ssl-certs/privkey.pem
        log_info "证书复制完成"
        return 0
    else
        log_error "证书文件不存在"
        return 1
    fi
}

# 更新nginx配置（只支持主域名）
update_nginx_config_main_only() {
    local domain=$1
    
    log_info "更新nginx配置（只支持主域名）..."
    
    cat > nginx.conf << EOF
# HTTP服务器 - 重定向到HTTPS
server {
    listen 80;
    server_name $domain www.$domain 124.220.186.165;
    
    # Let's Encrypt验证路径
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    
    # 其他所有请求重定向到HTTPS
    location / {
        return 301 https://$domain\$request_uri;
    }
}

# HTTPS服务器
server {
    listen 443 ssl http2;
    server_name $domain www.$domain 124.220.186.165;

    # SSL证书配置
    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;
    
    # SSL安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # 安全头
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # 设置客户端最大请求体大小
    client_max_body_size 100M;

    # 静态文件服务
    location /static/ {
        alias /app/pecco_backend/staticfiles/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # 媒体文件服务
    location /media/ {
        alias /app/pecco_backend/media/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # Django应用反向代理
    location / {
        proxy_pass http://web:8000;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Port 443;
        
        # 超时设置
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}
EOF
    
    log_info "nginx配置已更新"
}

# 主函数
main() {
    echo -e "${BLUE}SSL证书问题诊断和修复工具${NC}"
    echo "=================================="
    
    # 获取参数
    DOMAIN=${1:-"pecco.pet"}
    EMAIL=${2:-"huangxiaopan88@gmail.com"}
    
    log_info "域名: $DOMAIN"
    log_info "邮箱: $EMAIL"
    
    # 诊断问题
    log_info "开始诊断..."
    check_dns "$DOMAIN"
    check_dns "www.$DOMAIN"
    check_port "$DOMAIN" 80
    check_port "www.$DOMAIN" 80
    check_firewall
    test_http_connection "$DOMAIN"
    
    echo
    log_info "选择修复方案:"
    echo "1. 只为主域名获取证书 (推荐)"
    echo "2. 使用webroot模式重试"
    echo "3. 手动诊断"
    echo -n "请选择 (1-3): "
    read choice
    
    case $choice in
        1)
            if get_cert_main_domain_only "$DOMAIN" "$EMAIL"; then
                copy_certificates "$DOMAIN"
                update_nginx_config_main_only "$DOMAIN"
                log_info "重启nginx..."
                docker-compose -f docker-compose.prod.yml up -d nginx
                log_info "修复完成！"
            fi
            ;;
        2)
            if get_cert_webroot "$DOMAIN" "$EMAIL"; then
                copy_certificates "$DOMAIN"
                log_info "重启nginx..."
                docker-compose -f docker-compose.prod.yml up -d nginx
                log_info "修复完成！"
            fi
            ;;
        3)
            log_info "请检查以上诊断信息，手动解决问题"
            ;;
        *)
            log_error "无效选择"
            ;;
    esac
}

# 运行主函数
main "$@"
